using System;
using NUnit.Framework;
using ValidationFramework.Reflection;

namespace ValidationFramework.Tests
{
    public class RangeStringRuleTest
    {

        const string expectedMinimum = "b";
        const string expectedMaximum = "d";
        const string expectedErrorMessage = "expectedErrorMessage";
        const string expectedRuleSet = "EXPECTEDRULESET";
        [TestFixture]
        public sealed class Construction
        {

            [Test]
            public void Simple1()
            {
                var rule = new RangeStringRule(expectedMinimum, expectedMaximum);
                Assert.AreEqual(expectedMinimum, rule.Minimum);
                Assert.AreEqual(expectedMinimum, rule.Minimum);
            }


            [Test]
            [ExpectedException(typeof(ArgumentNullException), ExpectedMessage = "Value cannot be null.\r\nParameter name: minimum")]
            public void ExceptionMinimumNull3()
            {
                new RangeStringRule(null, expectedMaximum);
            }


            [Test]
            [ExpectedException(typeof(ArgumentException), ExpectedMessage = "String cannot be empty.\r\nParameter name: minimum")]
            public void ExceptionMinimumEmpty3()
            {
                new RangeStringRule(string.Empty, expectedMaximum);
            }


            [Test]
            [ExpectedException(typeof(ArgumentNullException), ExpectedMessage = "Value cannot be null.\r\nParameter name: maximum")]
            public void ExceptionMaximumNull3()
            {
                new RangeStringRule(expectedMinimum, null);
            }


            [Test]
            [ExpectedException(typeof(ArgumentException), ExpectedMessage = "String cannot be empty.\r\nParameter name: maximum")]
            public void ExceptionMaximumEmpty3()
            {
                new RangeStringRule(expectedMinimum, string.Empty);
            }


            [Test]
            public void Simple2()
            {
                var rule = new RangeStringRule(expectedMinimum, expectedMaximum);
                Assert.AreEqual(expectedMinimum, rule.Minimum);
                Assert.AreEqual(expectedMinimum, rule.Minimum);
                Assert.IsTrue(rule.EqualsMaximumIsValid);
                Assert.IsTrue(rule.EqualsMinimumIsValid);
            }


            [Test]
            [ExpectedException(typeof(ArgumentNullException), ExpectedMessage = "Value cannot be null.\r\nParameter name: minimum")]
            public void ExceptionMinimumNull2()
            {
                new RangeStringRule(null, expectedMaximum);
            }


            [Test]
            [ExpectedException(typeof(ArgumentException), ExpectedMessage = "String cannot be empty.\r\nParameter name: minimum")]
            public void ExceptionMinimumEmpty2()
            {
                new RangeStringRule(string.Empty, expectedMaximum);
            }


            [Test]
            [ExpectedException(typeof(ArgumentNullException), ExpectedMessage = "Value cannot be null.\r\nParameter name: maximum")]
            public void ExceptionMaximumNull2()
            {
                new RangeStringRule(expectedMinimum, null);
            }


            [Test]
            [ExpectedException(typeof(ArgumentException), ExpectedMessage = "String cannot be empty.\r\nParameter name: maximum")]
            public void ExceptionMaximumEmpty2()
            {
                new RangeStringRule(expectedMinimum, string.Empty);
            }


            [Test]
            public void Simple3()
            {
                var rule = new RangeStringRule(expectedMinimum, expectedMaximum);
                Assert.AreEqual(expectedMinimum, rule.Minimum);
                Assert.AreEqual(expectedMinimum, rule.Minimum);
                Assert.IsNull(rule.ErrorMessage);
                Assert.IsFalse(rule.UseErrorMessageProvider);
                Assert.IsTrue(rule.EqualsMaximumIsValid);
                Assert.IsTrue(rule.EqualsMinimumIsValid);
            }


            [Test]
            [ExpectedException(typeof(ArgumentNullException), ExpectedMessage = "Value cannot be null.\r\nParameter name: minimum")]
            public void MinimumNull1()
            {
                new RangeStringRule(null, expectedMaximum);
            }


            [Test]
            [ExpectedException(typeof(ArgumentException), ExpectedMessage = "String cannot be empty.\r\nParameter name: minimum")]
            public void MinimumEmpty2()
            {
                new RangeStringRule(string.Empty, expectedMaximum);
            }


            [Test]
            [ExpectedException(typeof(ArgumentNullException), ExpectedMessage = "Value cannot be null.\r\nParameter name: maximum")]
            public void MaximumNull1()
            {
                new RangeStringRule(expectedMinimum, null);
            }


            [Test]
            [ExpectedException(typeof(ArgumentException), ExpectedMessage = "String cannot be empty.\r\nParameter name: maximum")]
            public void MaximumEmpty1()
            {
                new RangeStringRule(expectedMinimum, string.Empty);
            }

        }
        [TestFixture]
        public sealed class Equality
        {
            [Test]
            public void Simple()
            {
                var rule1 = new RangeStringRule(expectedMinimum, expectedMaximum);
                var rule2 = new RangeStringRule(expectedMinimum, expectedMaximum);

                Assert.IsTrue(rule1.IsEquivalent(rule2));

                rule1 = new RangeStringRule("a", "d");
                rule2 = new RangeStringRule("b", "d");
                Assert.IsFalse(rule1.IsEquivalent(rule2));

                rule1 = new RangeStringRule("a", "d");
                rule2 = new RangeStringRule("a", "c");
                Assert.IsFalse(rule1.IsEquivalent(rule2));
            }

        }
        [TestFixture]
        public sealed class RuleInterpretation
        {
            [Test]
            public void Simple()
            {

                var rule = new RangeStringRule(expectedMinimum, expectedMaximum);
                Assert.IsNotNull(rule.RuleInterpretation);
            }
        }
        [TestFixture]
        public sealed class Validate
        {
            [Test]
            public void Simple()
            {
                var rule = new RangeStringRule(expectedMinimum, expectedMaximum);
                Assert.IsTrue(rule.Validate(null, null, null, null));
                Assert.IsFalse(rule.Validate(null, "a", null, null));
                Assert.IsTrue(rule.Validate(null, "b", null, null));
                Assert.IsTrue(rule.Validate(null, "c", null, null));
                Assert.IsTrue(rule.Validate(null, "d", null, null));
                Assert.IsFalse(rule.Validate(null, "e", null, null));
            }
        }
        [TestFixture]
        public sealed class CheckTypes
        {
            [Test]
            public void Simple()
            {
                var rule = new RangeStringRule(expectedMinimum, expectedMaximum);
                rule.CheckType(new MockInfoDescriptor(TypePointers.StringTypeHandle, "foo"));
            }


            [Test]
            [ExpectedException(typeof(ArgumentException), ExpectedMessage = "Member 'foo' must be a 'System.String' to be used for the ValidationFramework.RangeStringRule. Actual Type 'System.Int32'.\r\nParameter name: value")]
            public void ExceptionInvalidType()
            {
                var rule = new RangeStringRule(expectedMinimum, expectedMaximum);
                rule.CheckType(new MockInfoDescriptor(TypePointers.IntTypeHandle, "foo"));
            }
        }

    }
}